/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "Pattern.h"
#include "OrderedReader.h"

XMPattern::XMPattern( int channels, resource::Resource * resource )
{
	//header length
	unsigned pattern_header_length = read_long_little_endian( resource );

	char packing_type;
	//packing thype (always 0, as format documentation says)
	resource->read( &packing_type, 1 );

	//number of rows in pattern (1..256)
	unsigned short row_count = read_short_little_endian( resource );

	rows.resize( row_count );
	int i;
	for( i = 0; i < (int)rows.size(); ++i )
	{
		rows[i].resize( channels );
	}

	//packed patterndata size
	unsigned short packed_pattern_size = read_short_little_endian( resource );

	//reset volume column
	for( i = 0; i < row_count; ++i )
	{
		typedef unsigned char uchar;
		for( int k = 0; k < channels; ++k )
			rows[i][k].volume = uchar(0xFF);
	}

	//read pattern only if packed_pattern_size > 0, otherwise it's empty
	if ( packed_pattern_size > 0 )
	{
		for ( int i = 0; i < row_count; ++i )
		{
			for ( int k = 0; k < channels; ++k )
			{
				//read flag
				char flag;
				resource->read( &flag, 1 );

				if( flag & 0x80 ) //this note is compressed
				{
					if ( flag & 1 ) //note follows
					{
						resource->read( &rows[i][k].note, 1 );
					}
					if ( flag & 2 ) //instrument follows
					{
						resource->read( &rows[i][k].instrument, 1 );
					}
					if ( flag & 4 ) //volume column byte follows
					{
						resource->read( &rows[i][k].volume, 1 );
					}
					if ( flag & 8 ) //effect follows
					{
						resource->read( &rows[i][k].effect, 1 );
					}
					if ( flag & 16 ) //effect params follows
					{
						resource->read( &rows[i][k].effect_parameter, 1 );
					}
				}
				else
				{
					//no compression
					rows[i][k].note = flag;
					resource->read( &rows[i][k].instrument, 1 );
					resource->read( &rows[i][k].volume, 1 );
					resource->read( &rows[i][k].effect, 1 );
					resource->read( &rows[i][k].effect_parameter, 1 );
				}
			}
		}
	}
}

